//
//  PointsController.swift
//  hello
//
//  Created by 赵康 on 2025/5/28.
//

import Fluent
import Vapor

struct PointsController: RouteCollection {
  func boot(routes: any RoutesBuilder) throws {
    let points = routes.grouped("\(RouteEnum.points.rawValue)")
    let protected = points.grouped(AuthMiddleware())
    
    // 查询积分余额
    protected.get("\(RouteEnum.pointBalance.rawValue)", use: getPointsBalance)
    
    // 查询积分历史
    protected.get("\(RouteEnum.pointHistory.rawValue)", use: getPointsHistory)
    
    // 分享获取积分
    protected.post("\(RouteEnum.pointShare.rawValue)", use: shareForPoints)
    
    // 使用积分兑换服务（VIP折扣、AI解析等）- 只是接口框架，没有具体实现
    protected.post("\(RouteEnum.pointExchange.rawValue)", use: exchangePoints)
    
    // 获取里程碑进度信息
    protected.get("\(RouteEnum.milestoneProgress.rawValue)", use: getMilestoneProgress)
  }
  
  // 获取用户积分余额
  @Sendable
  func getPointsBalance(_ req: Request) async throws -> PointsBalanceResponse {
    let userID = try req.authenticatedUserID
    
    guard let user = try await User.find(userID, on: req.db) else {
      throw Abort(.notFound, reason: "用户不存在")
    }
    
    // 确保用户的总打卡天数是准确的
    let checkInDates = try await getCompletedCheckInDates(userID: userID, db: req.db)
    if user.totalCheckIns != checkInDates.count {
      user.totalCheckIns = checkInDates.count
      try await user.save(on: req.db)
    }
    
    // 获取今天的开始时间
    let today = Calendar.mondayFirst.startOfDay(for: Date())
    
    // 计算今日获得的积分
    let todayPointsHistory = try await PointsHistory.query(on: req.db)
      .filter(\.$user.$id == userID)
      .filter(\.$createdAt >= today)
      .all()
    
    let todayEarnedPoints = todayPointsHistory
      .filter { $0.amount > 0 }
      .reduce(0) { $0 + $1.amount }
    
    return PointsBalanceResponse(
      points: user.points,
      totalCheckIns: user.totalCheckIns,
      currentStreak: user.currentStreak,
      todayEarnedPoints: todayEarnedPoints
    )
  }
  
  // 获取积分历史记录
  @Sendable
  func getPointsHistory(_ req: Request) async throws -> PointsHistoryListResponse {
    let userID = try req.authenticatedUserID
    
    // 分页参数
    let page = try req.query.get(Int.self, at: "page") ?? 1
    let pageSize = try req.query.get(Int.self, at: "page_size") ?? 20
    
    // 查询类型过滤（可选）
    let typeInt = try? req.query.get(Int.self, at: "type")
    let type = typeInt.flatMap { PointsHistoryType(rawValue: $0) }
    
    var query = PointsHistory.query(on: req.db)
      .filter(\.$user.$id == userID)
      .sort(\.$createdAt, .descending)
    
    // 如果指定了类型，则添加类型过滤
    if let type = type {
      query = query.filter(\.$type == type)
    }
    
    let items = try await query
      .paginate(PageRequest(page: page, per: pageSize))
    
    let response = try items.map { history in
      try PointsHistory.Response(
        id: history.requireID(),
        amount: history.amount,
        balance: history.balance,
        type: history.type,
        description: history.description,
        createdAt: history.createdAt
      )
    }
    
    return PointsHistoryListResponse(
      items: response.items,
      metadata: response.metadata
    )
  }
  
  // 每日分享获取积分
  @Sendable
  func shareForPoints(_ req: Request) async throws -> BasicResponse {
    let userID = try req.authenticatedUserID
    
    guard let user = try await User.find(userID, on: req.db) else {
      throw Abort(.notFound, reason: "用户不存在")
    }
    
    // 判断今天是否已经获得分享积分
    let today = Calendar.mondayFirst.startOfDay(for: Date())
    
    // 查询今日是否已有分享积分记录
    let hasTodayShared = try await PointsHistory.query(on: req.db)
      .filter(\.$user.$id == userID)
      .filter(\.$type == .share)
      .filter(\.$createdAt >= today)
      .first() != nil
    
    if hasTodayShared {
      throw Abort(.badRequest, reason: "今日已获得分享积分")
    }
    
    // 增加5积分
    user.points += 5
    try await user.save(on: req.db)
    
    // 创建积分历史记录
    let pointsHistory = PointsHistory(
      userID: userID,
      amount: 5,
      balance: user.points,
      type: .share,
      description: "每日分享奖励",
      createdAt: Date()
    )
    try await pointsHistory.save(on: req.db)
    
    return BasicResponse(
      success: true,
      message: "分享成功，获得5积分"
    )
  }
  
  // 使用积分兑换服务（预留功能，暂不实现具体逻辑）
  @Sendable
  func exchangePoints(_ req: Request) async throws -> BasicResponse {
    let userID = try req.authenticatedUserID
    
    let exchange = try req.content.decode(ExchangePointsRequest.self)
    
    guard let user = try await User.find(userID, on: req.db) else {
      throw Abort(.notFound, reason: "用户不存在")
    }
    
    // 检查积分是否足够
    guard user.points >= exchange.points else {
      throw Abort(.badRequest, reason: "积分不足")
    }
    
    // 根据兑换类型执行不同操作
    switch exchange.type {
    case .vipDiscount:
      // 积分兑换VIP折扣功能，暂不实现
      return BasicResponse(
        success: false,
        message: "VIP折扣功能暂未开放"
      )
      
    case .aiAnalysis:
      // 积分兑换AI解析功能，暂不实现
      return BasicResponse(
        success: false,
        message: "AI解析功能暂未开放"
      )
      
    default:
      throw Abort(.badRequest, reason: "不支持的兑换类型")
    }
  }
  
  // 获取里程碑进度信息
  @Sendable
  func getMilestoneProgress(_ req: Request) async throws -> MilestoneProgressResponse {
    let userID = try req.authenticatedUserID
    
    guard let user = try await User.find(userID, on: req.db) else {
      throw Abort(.notFound, reason: "用户不存在")
    }
    
    // 确保用户的总打卡天数是准确的
    let checkInDates = try await getCompletedCheckInDates(userID: userID, db: req.db)
    if user.totalCheckIns != checkInDates.count {
      user.totalCheckIns = checkInDates.count
      try await user.save(on: req.db)
    }
    
    // 里程碑天数和对应的奖励积分
    let milestones: [(days: Int, points: Int)] = [
      (7, 100),
      (30, 200),
      (60, 300),
      (100, 600),
      (200, 1000),
      (360, 2000)
    ]
    
    // 计算当前里程碑周期中的天数
    let currentCycleDays = user.totalCheckIns - user.lastMilestoneAwarded
    
    // 找出下一个要达到的里程碑
    var nextMilestone: Milestone? = nil
    var allMilestones: [Milestone] = []
    
    for milestone in milestones.sorted(by: { $0.days < $1.days }) {
      let isAchieved = currentCycleDays >= milestone.days
      
      allMilestones.append(Milestone(
        days: milestone.days,
        points: milestone.points,
        daysRemaining: max(0, milestone.days - currentCycleDays),
        achieved: isAchieved
      ))
      
      if nextMilestone == nil && !isAchieved {
        nextMilestone = Milestone(
          days: milestone.days,
          points: milestone.points,
          daysRemaining: milestone.days - currentCycleDays,
          achieved: false
        )
      }
    }
    
    return MilestoneProgressResponse(
      totalCheckIns: user.totalCheckIns,
      currentCycleDays: currentCycleDays,
      nextMilestone: nextMilestone,
      allMilestones: allMilestones
    )
  }
  
  // 获取所有有效的打卡日期
  private func getCompletedCheckInDates(userID: UUID, db: Database) async throws -> [Date] {
    guard let user = try await User.find(userID, on: db) else {
      throw Abort(.notFound, reason: "用户不存在")
    }
    
    // 获取所有历史记录
    let allHistories = try await History.query(on: db)
      .filter(\.$user.$id == userID)
      .all()
    
    // 按日期分组并累加时长
    var dailyListeningTime: [Date: Double] = [:]
    
    for history in allHistories {
      guard let date = history.lastListenedAt else { continue }
      let dayStart = Calendar.mondayFirst.startOfDay(for: date)
      let currentTotal = dailyListeningTime[dayStart] ?? 0
      dailyListeningTime[dayStart] = currentTotal + history.listenedDuration
    }
    
    // 筛选出达到每日目标的日期
    return dailyListeningTime
      .filter { $0.value >= user.dailyGoal }
      .keys
      .sorted()
  }
}

// 积分余额响应
struct PointsBalanceResponse: Content {
  let points: Int
  let totalCheckIns: Int
  let currentStreak: Int
  let todayEarnedPoints: Int
}

// 积分历史列表响应
struct PointsHistoryListResponse: Content {
  let items: [PointsHistory.Response]
  let metadata: PageMetadata
}

// 积分兑换请求
struct ExchangePointsRequest: Content {
  let points: Int
  let type: PointsHistoryType
}

// 里程碑信息
struct Milestone: Content {
  let days: Int
  let points: Int
  let daysRemaining: Int
  let achieved: Bool
}

// 里程碑进度响应
struct MilestoneProgressResponse: Content {
  let totalCheckIns: Int
  let currentCycleDays: Int
  let nextMilestone: Milestone?
  let allMilestones: [Milestone]
} 
